
package com.dstz.form.util;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;

import org.apache.commons.lang3.StringUtils;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.dstz.base.core.util.StringUtil;
import com.dstz.form.constants.ViewConstants.ViewTuoMingConstants;
import com.dstz.form.model.custsql.FormCustSqlFields;

import cn.hutool.core.exceptions.UtilException;

/**
 * 过敏工具类
 */
public class TuoMingUtil {
	
	private static final Integer PHONE_LEN = 11;
	
	private static final Integer TELPHONE_LEN = 10;
	
	private static final Integer ID_CARD_LEN = 18;
	
	private static final Integer NEED_DESENSITIZATION_ADDRESS_LEN = 5;
	
	private static final Integer NEED_DESENSITIZATION_QQ_LEN = 5;
	
	private static final Integer NEED_DESENSITIZATION_WECHAT_LEN = 5;
	
	private TuoMingUtil() {
		
	}
	
	/**
	 * 对数据进行脱敏处理
	 * 
	 * @param commonFieldList
	 * @param listData
	 * @return void
	 * @author xianggang
	 * @date 2018年4月5日 下午7:09:45
	 */
	public static void tuoMing(List<FormCustSqlFields> commonFieldList, JSONArray listData) {
		
		// 脱敏
		for (FormCustSqlFields fieldSetting : commonFieldList) {
			String fuzz = fieldSetting.getFuzz();
			if (StringUtil.isNotEmpty(fuzz)) {
				// 自定义脱敏
				customerFuzz(listData, fieldSetting.getFieldName(), fuzz);
			}
		}
		
	}
	
	// 自定义脱敏
	private static void customerFuzz(JSONArray listData, String fieldName, String fuzz) {
		
		String[] fuzzSplit = fuzz.split(",");
		
		int fuzzSize = fuzzSplit.length;
		
		int left = Integer.parseInt(fuzzSplit[0]);
		if (left <= 0) {
			left = 0;
		}
		
		// 如果只有一位 比如 1, 那么只会显示第一位 如向刚 会替换为 向**
		int right = 0;
		String xing = "**";
		
		// 如果有两位,比如 3,3 那么会显示左边3个字符和右边3个字符 中间的加四个星 如 我爱你一生一世到永久 会替换为 我爱你****到永久
		if (fuzzSize == 2) {
			right = Integer.parseInt(fuzzSplit[1]);
			if (right <= 0) {
				right = 0;
			}
			xing = "****";
		}
		// 如果有三位,比如 1,2,3  那么会显示左边1个字符和右边2个字符 中间的3个加星 如 我爱你一生一世到永久 会替换为 我***永久
		if (fuzzSize == 3) {
			right = Integer.parseInt(fuzzSplit[1]);
			if (right <= 0) {
				right = 0;
			}
			xing = "********************".substring(0, Integer.parseInt(fuzzSplit[2]));
		}
		
		for (Object dataJson : listData) {
			JSONObject dataJo = (JSONObject) dataJson;
			if (dataJo.containsKey(fieldName) && StringUtils.isNotEmpty(dataJo.getString(fieldName))) {
				String value = dataJo.getString(fieldName);
				String valueStr = value.toString();
				int valueStrLength = valueStr.length();
				
				// 如果开始位置比值长度更长,则不需要脱敏
				if (left >= valueStrLength) {
					continue;
				}
				
				// 如果开始位置+长度比值长度更长,则只脱敏开始到最后的
				int size = left + right;
				if (size >= valueStrLength) {
					// 只截取左边的
					valueStr = valueStr.substring(0, left) + xing;
					dataJo.put(fieldName, valueStr);
					continue;
				}
				
				if (right == 0) {
					valueStr = valueStr.substring(0, left) + xing;
				} else {
					valueStr = valueStr.substring(0, left) + xing
					        + valueStr.substring(valueStrLength - right, valueStrLength);
				}
				
				dataJo.put(fieldName, valueStr);
			}
		}
	}
	
	// 对字段进行脱敏
	public static String tuoMing(String data, int tuoMingType) {
		switch (tuoMingType) {
			case ViewTuoMingConstants.TUOMING_PHONE:
				
				return desensPhone(data);
			case ViewTuoMingConstants.TUOMING_TEL_PHONE:
				
				return desensTelPhone(data);
			case ViewTuoMingConstants.TUOMING_IDCARD:
				
				return desensIdCard(data);
			case ViewTuoMingConstants.TUOMING_NAME:
				
				return desensName(data);
			case ViewTuoMingConstants.TUOMING_BANKCARD:
				
				return desensBankCardNo(data);
			case ViewTuoMingConstants.TUOMING_ADDRESS:
				
				return desensAddress(data);
			case ViewTuoMingConstants.TUOMING_QQ:
				
				return desensQQ(data);
			case ViewTuoMingConstants.TUOMING_WEIXIN:
				
				return desensWechat(data);
			default:
				throw new UtilException("暂不支持该脱敏类型" + tuoMingType);
		}
	}
	
	/**
	 * 手机号脱敏处理
	 * 
	 * @param phone 手机号
	 * @return 手机号前3位+****+手机号后4位
	 */
	public static String desensPhone(String phone) {
		if (StringUtils.isBlank(phone)) {
			return phone;
		}
		phone = phone.replaceAll(" ", "");
		if (StringUtils.isBlank(phone) || phone.length() != PHONE_LEN) {
			return phone;
		}
		return new StringBuilder(phone).replace(3, 7, "****").toString();
	}
	
	/**
	 * 姓名脱敏
	 * 
	 * @param name 姓名脱敏
	 * @return 姓名 前1位+****
	 */
	public static String desensName(String bankCardNo) {
		if (StringUtils.isBlank(bankCardNo)) {
			return bankCardNo;
		}
		return new StringBuilder(bankCardNo).replace(1, bankCardNo.length(), "****").toString();
	}
	
	/**
	 * 银行卡号脱敏
	 * 
	 * @param bankCardNo 银行卡号脱敏
	 * @return 银行卡号 前3位+****+银行卡号后4位
	 */
	public static String desensBankCardNo(String bankCardNo) {
		if (StringUtils.isBlank(bankCardNo) || bankCardNo.length() < 11) {
			return bankCardNo;
		}
		return new StringBuilder(bankCardNo).replace(3, 7, "****").toString();
	}
	
	/**
	 * 固定电话脱敏处理
	 * 
	 * @param phone 固定电话
	 * @return 固话倒数6~4*号 010-66***899
	 */
	public static String desensTelPhone(String phone) {
		if (StringUtils.isBlank(phone) || phone.length() < TELPHONE_LEN) {
			return phone;
		}
		return new StringBuilder(phone).replace(7, 9, "***").toString();
	}
	
	/**
	 * 身份证脱敏处理
	 * 
	 * @param idCard 身份证号
	 * @return 身份证前6位+*******+身份证后4位
	 */
	public static String desensIdCard(String idCard) {
		if (StringUtils.isBlank(idCard) || idCard.length() != ID_CARD_LEN) {
			return idCard;
		}
		return new StringBuilder(idCard).replace(6, 14, "********").toString();
	}
	
	/**
	 * 地址脱敏处理
	 * 
	 * @param address 地址
	 * @return 地址最后5位用*代替
	 */
	public static String desensAddress(String address) {
		int addressLen;
		if (StringUtils.isBlank(address) || (addressLen = address.length()) < NEED_DESENSITIZATION_ADDRESS_LEN) {
			return address;
		}
		return new StringBuilder(address).replace(addressLen - 5, addressLen, "*****").toString();
	}
	
	/**
	 * QQ号脱敏处理
	 * 
	 * @param qq QQ号
	 * @return QQ号前2位+****+QQ号后3位
	 */
	public static String desensQQ(String qq) {
		int qqLen;
		if (StringUtils.isBlank(qq) || (qqLen = qq.length()) < NEED_DESENSITIZATION_QQ_LEN) {
			return qq;
		}
		return new StringBuilder(qq).replace(2, qqLen - 3, makeRepeatableStar(qqLen - 5)).toString();
	}
	
	/**
	 * 微信号脱敏处理
	 * 
	 * @param wechat 微信号
	 * @return 如果微信号是11位，按手机号方式脱敏处理；否则按QQ号脱敏处理
	 */
	public static String desensWechat(String wechat) {
		int wechatLen;
		if (StringUtils.isBlank(wechat) || (wechatLen = wechat.length()) < NEED_DESENSITIZATION_WECHAT_LEN) {
			return wechat;
		}
		return wechatLen == PHONE_LEN ? desensPhone(wechat) : desensQQ(wechat);
	}
	
	/**
	 * 生产多个*
	 * 
	 * @param repeatCount 重复个数
	 * @return
	 */
	private static String makeRepeatableStar(int repeatCount) {
		return makeRepeatableStr("*", repeatCount);
	}
	
	/**
	 * 生产多个重复字符
	 * 
	 * @param str 重复字符
	 * @param repeatCount 重复个数
	 * @return
	 */
	private static String makeRepeatableStr(String str, int repeatCount) {
		if (StringUtils.isBlank(str)) {
			return "";
		}
		StringBuilder sb = new StringBuilder(repeatCount);
		for (int i = 0; i < repeatCount; i++) {
			sb.append(str);
		}
		return sb.toString();
	}
	
	/**
	 * 手机号字段集
	 */
	private static final List<String> PHONE_FIELD_LIST = Arrays.asList("phone", "telephoneNumber", "telephone",
	        "mobile", "mobileNumber", "mobilePhone", "debtorPhone", "storeContactPhone", "phoneNumber");
	
	/**
	 * 身份证字段集
	 */
	private static final List<String> ID_CARD_FIELD_LIST = Arrays.asList("idCard", "certificateId", "ecodeOrIdcard",
	        "idNumber", "idcard", "splitIdCard");
	
	/**
	 * 地址字段集
	 */
	private static final List<String> ADDRESS_LIST = Arrays.asList("address", "debtorAddress");
	
	/**
	 * QQ字段集
	 */
	private static final List<String> QQ_LIST = Arrays.asList("qq");
	
	/**
	 * 固定电话电话
	 */
	private static final List<String> TELPHONE_LIST = Arrays.asList("companyPhoneNumber", "workPhone");
	
	/**
	 * 微信字段集
	 */
	private static final List<String> WECHAT_LIST = Arrays.asList("wechat");
	
	/**
	 * 关键字脱敏
	 * 
	 * @param data 原始数据
	 * @throws IllegalAccessException
	 */
	public static void doKeywordsDesensitization(List<Object> data) throws IllegalAccessException {
		for (Object obj : data) {
			Field[] fields = obj.getClass().getDeclaredFields();
			for (Field field : fields) {
				field.setAccessible(true);
				String fieldName = field.getName();
				// 手机号
				if (PHONE_FIELD_LIST.contains(fieldName)) {
					field.set(obj, TuoMingUtil.desensPhone((String) field.get(obj)));
					continue;
				}
				// 身份证
				if (ID_CARD_FIELD_LIST.contains(fieldName)) {
					field.set(obj, TuoMingUtil.desensIdCard((String) field.get(obj)));
					continue;
				}
				// 地址
				if (ADDRESS_LIST.contains(fieldName)) {
					field.set(obj, TuoMingUtil.desensAddress((String) field.get(obj)));
					continue;
				}
				// QQ
				if (QQ_LIST.contains(fieldName)) {
					field.set(obj, TuoMingUtil.desensQQ((String) field.get(obj)));
					continue;
				}
				// 微信
				if (WECHAT_LIST.contains(fieldName)) {
					field.set(obj, TuoMingUtil.desensWechat((String) field.get(obj)));
					continue;
				}
				
				// 固定电话
				if (TELPHONE_LIST.contains(fieldName)) {
					field.set(obj, TuoMingUtil.desensTelPhone((String) field.get(obj)));
					continue;
				}
			}
		}
	}
}